package com.juren.controller.test.notify;

/**
 * @ClassName Target
 * @Description 两个线程，一个线程将某个对象的某个成员变量的值加1，而另外一个线程将这个成员变量的值减1.使得该变量的值始终处于[0,2].初始值为0.
 * @Author zhangtao
 * @Date 2019/6/4 10:43
 * @Version 1.0
 **/
public class Target {

    private int count;

    public synchronized void increase() {
        if (count == 2) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count++;
        System.out.println(Thread.currentThread().getName() + ":" + count);
        notify();
    }

    public synchronized void decrease() {
        if (count == 0) {
            try {
                //等待，由于Decrease线程调用的该方法,
                //所以Decrease线程进入对象t(main函数中实例化的)的**等待池**，并且释放对象t的锁
                wait();//Object类的方法
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        count--;
        System.out.println(Thread.currentThread().getName() + ":" + count);

        //唤醒线程Increase，Increase线程从等待池到锁池
        notify();
    }
}

class Increase extends Thread {
    private Target t;

    public Increase(Target t) {
        this.t = t;
    }

    @Override
    public void run() {
        for (int i = 0; i < 30; i++) {
            try {
                Thread.sleep((long) (Math.random() * 500));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            t.increase();
        }

    }

}

class Decrease extends Thread {

    private Target t;

    public Decrease(Target t) {
        this.t = t;
    }

    @Override
    public void run() {
        for (int i = 0; i < 30; i++) {
            try {
                //随机睡眠0~500毫秒
                //sleep方法的调用，不会释放对象t的锁
                Thread.sleep((long) (Math.random() * 500));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            t.decrease();

        }

    }

}
